#include "stdafx.h"

MainWindow::MainWindow(Game& game) :
	mClassName("QQ_WINDOW_PEW"),
	mRunning(false),
	mGame(game)
{
}


void MainWindow::create(int width, int height, const std::string& text)
{
	WNDCLASSEX winClass = {0}; 
	winClass.lpszClassName = mClassName.c_str();
	winClass.cbSize        = sizeof(WNDCLASSEX);
	winClass.style         = CS_HREDRAW | CS_VREDRAW;
	winClass.lpfnWndProc   = globalOnEvent;
	winClass.hInstance = globals::hInstance;
	winClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
	winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	
	if( !RegisterClassEx(&winClass) )
		return;

	mWndHandle = CreateWindow(mClassName.c_str(), text.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, width, height, nullptr, 0, nullptr, this);
	
	globals::d3d = Direct3DCreate9(DIRECT3D_VERSION);

	D3DDISPLAYMODE displayMode;
	globals::d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode);

	D3DPRESENT_PARAMETERS presentParams = {0};
	presentParams.Windowed = TRUE;
	presentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
	presentParams.BackBufferFormat = displayMode.Format;
	presentParams.EnableAutoDepthStencil = TRUE;
	presentParams.AutoDepthStencilFormat = D3DFMT_D16;
	presentParams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

	globals::d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mWndHandle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParams, &globals::d3dDevice);

	D3DXMATRIX matView;
	D3DXMatrixLookAtLH( &matView, &D3DXVECTOR3(0.0f, 0.0f,-10.0f), 
								  &D3DXVECTOR3(0.0f, 0.0f, 0.0f), 
								  &D3DXVECTOR3(0.0f, 1.0f, 0.0f ) );
	globals::d3dDevice->SetTransform( D3DTS_VIEW, &matView );

	D3DXMATRIX matProj;
	D3DXMatrixPerspectiveFovLH( &matProj, D3DXToRadian( 70.0f ), 1.0f, 1.0f, 200.0f );
	globals::d3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );

	globals::d3dDevice->SetRenderState( D3DRS_LIGHTING,  FALSE );
}


MainWindow::~MainWindow(void)
{
	UnregisterClass(mClassName.c_str(), globals::hInstance);

	if( globals::d3dDevice != NULL )
		globals::d3dDevice->Release();

	if( globals::d3d != NULL )
		globals::d3d->Release();
}



HWND MainWindow::getHandle() const
{
	return mWndHandle;
}


void MainWindow::show()
{
	ShowWindow(mWndHandle, TRUE);
	mRunning = true;
}


void MainWindow::close()
{
	ShowWindow(mWndHandle, FALSE);
	mRunning = false;
}


bool MainWindow::isRunning()
{
	return mRunning;
}


void MainWindow::update()
{
	UpdateWindow(mWndHandle);
}


void MainWindow::doEvents()
{
	MSG Message;
	while (PeekMessage(&Message, nullptr, 0, 0, PM_REMOVE))
	{
		TranslateMessage(&Message);
		DispatchMessage(&Message);
	}
}


LRESULT CALLBACK MainWindow::globalOnEvent(HWND handle, UINT message, WPARAM wParam, LPARAM lParam)
{	
	MainWindow* wnd = reinterpret_cast<MainWindow*>(GetWindowLongPtr(handle, GWLP_USERDATA));

	switch(message)
	{
	case WM_CREATE:
		{
			CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(lParam);
			long This = reinterpret_cast<long>(cs->lpCreateParams);
			SetWindowLongPtr(handle, GWLP_USERDATA, This);
		} break;
	case WM_DESTROY:
	case WM_CLOSE:
		if(wnd) 
			wnd->close();
		else 
			PostQuitMessage(0);
		return 0;
	}

	return wnd != nullptr ? wnd->mGame.doMessage(handle, message, wParam, lParam) : DefWindowProc(handle, message, wParam, lParam);
}